package com.guozcc.bootweb.platform.config;

import org.springframework.boot.autoconfigure.task.TaskExecutionProperties;
import org.springframework.boot.autoconfigure.task.TaskSchedulingProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ThreadPoolExecutor;


@EnableAsync // 开启
@Configuration
public class ThreadConfig {

//    TaskExecutionAutoConfiguration异步任务装配
//    TaskSchedulingAutoConfiguration定时任务装配
//            也可以自己配置多个线程池，使用的时候指定,实现线程池隔离

    //使用TaskExecutionProperties配置
    @Bean(name = "commonThreadPoolTaskExecutor")
    public ThreadPoolTaskExecutor asyncExecutor(TaskExecutionProperties taskExecutionProperties) {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //配置核心线程数
        executor.setCorePoolSize(taskExecutionProperties.getPool().getCoreSize());
        //配置最大线程数
        executor.setMaxPoolSize(taskExecutionProperties.getPool().getMaxSize());
        //配置队列大小
        executor.setQueueCapacity(taskExecutionProperties.getPool().getQueueCapacity());
        //配置线程池中的线程的名称前缀
        executor.setThreadNamePrefix(taskExecutionProperties.getThreadNamePrefix());
        // 允许回收核心线程
        executor.setAllowCoreThreadTimeOut(true);
        // CALLER_RUNS: 不在新线程中执行任务，而是有调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //执行初始化
        executor.initialize();
        return executor;
    }

    //使用自定义配置
    @Bean(name = "guozccThreadPoolTaskExecutor")
    public ThreadPoolTaskExecutor imageThreadPool() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 设置核心线程数,它是可以同时被执行的线程数量
        executor.setCorePoolSize(2);
        // 设置最大线程数,缓冲队列满了之后会申请超过核心线程数的线程
        executor.setMaxPoolSize(10);
        // 设置缓冲队列容量,在执行任务之前用于保存任务
        executor.setQueueCapacity(50);
        // 设置线程生存时间（秒）,当超过了核心线程出之外的线程在生存时间到达之后会被销毁
        executor.setKeepAliveSeconds(60);
        // 设置线程名称前缀
        executor.setThreadNamePrefix("guozcc-execution-task-");
        // 设置拒绝策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 等待所有任务结束后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        //初始化
        executor.initialize();
        return executor;
    }
}


// 这里还有很多配置

// corePoolSize - 保留在池中的线​​程数，即使它们是空闲的，除非设置allowCoreThreadTimeOut
// maximumPoolSize – 池中允许的最大线程数
// keepAliveTime – 当线程数大于核心时，这是多余的空闲线程在终止前等待新任务的最长时间。
// unit – keepAliveTime参数的时间单位
// workQueue – 用于在执行任务之前保存任务的队列。此队列将仅保存由execute方法提交的Runnable任务。
// threadFactory – 执行器创建新线程时使用的工厂
// handler – 由于达到线程边界和队列容量而阻塞执行时使用的处理程序